/*
* Copyright (c) Huawei Technologies Co., Ltd. 2023. All rights reserved.
*/

#include "vpc_pipeline/vpc_pipe_format.h"
#include "dvpp_cmdlist_log.h"
#include "vpc_format_def.h"
#include "format_field.h"

static uint32_t trans_pixel_fmt_to_bytes(vpc_pixel_fmt_e fmt)
{
    switch (fmt) {
        case IDEL : {return 0;}      // IDLE:0字节
        case D8   : {return 1;}      // D8:1字节
        case D16  : {return 2;}      // D16：2字节
        case D24  : {return 3;}      // D24：3字节
        case D32  : {return 4;}      // D32：4字节
        case D48  : {return 6;}      // D48：6字节
        case D64  : {return 8;}      // D64：8字节
        case D96  : {return 12;}     // D96：12字节
        case YUV422PKT : {return 2;} // YUV422PKT：2字节
    }

    return 0;
}

uint32_t vpc_pipe_get_du_val(const vpc_fmt_info_t *fmt_info, uint32_t port)
{
    if (port == PORT0) {
        return fmt_info->port_du.p0;
    }

    if (port == PORT1) {
        return fmt_info->port_du.p1;
    }

    return fmt_info->port_du.p2;
}

vpc_pixel_fmt_e vpc_pipe_get_pixel_fmt(const vpc_fmt_info_t *fmt_info, uint32_t port)
{
    if (port == PORT0) {
        return fmt_info->port_fmt.p0;
    }

    if (port == PORT1) {
        return fmt_info->port_fmt.p1;
    }

    return fmt_info->port_fmt.p2;
}

uint32_t vpc_pipe_get_vpc_format(const vpc_fmt_info_t *fmt_info)
{
    return fmt_info->vpc_pic_fmt;
}

uint32_t vpc_pipe_get_pixel_step(const vpc_fmt_info_t *fmt_info, uint32_t dir)
{
    return dir == X ? fmt_info->pixel_step.x : fmt_info->pixel_step.y;
}

uint32_t vpc_pipe_get_line_size(const vpc_fmt_info_t *fmt_info, uint32_t width, uint32_t port)
{
    return port == PORT0 ? width : width / vpc_pipe_get_pixel_step(fmt_info, X);
}

uint32_t vpc_pipe_get_frame_height(const vpc_fmt_info_t *fmt_info, uint32_t height, uint32_t port)
{
    return port == PORT0 ? height : height / vpc_pipe_get_pixel_step(fmt_info, Y);
}

uint32_t vpc_pipe_get_stride(const vpc_fmt_info_t *fmt_info, uint32_t y_stride, uint32_t port)
{
    uint32_t xstep;
    uint32_t bytes;
    vpc_pixel_fmt_e pixel_fmt;
    if (port == PORT0) {
        return y_stride;
    }

    // RGB Plannar 三个分量的stride都一样;YUV Plannar 三个分量stride和SP格式一样
    if (fmt_info->plannar_fmt == RGB_PLANNAR) {
        return y_stride;
    }

    xstep = vpc_pipe_get_pixel_step(fmt_info, X);
    pixel_fmt = vpc_pipe_get_pixel_fmt(fmt_info, port);
    bytes = trans_pixel_fmt_to_bytes(pixel_fmt);
    return y_stride * bytes / xstep;
}

uint32_t vpc_pipe_get_offset(const vpc_fmt_info_t *fmt_info, uint32_t width, uint32_t port)
{
    uint32_t xstep;
    vpc_pixel_fmt_e pixel_fmt = vpc_pipe_get_pixel_fmt(fmt_info, port);
    uint32_t bytes = trans_pixel_fmt_to_bytes(pixel_fmt);

    if (port == PORT0) {
        return width * trans_pixel_fmt_to_bytes(pixel_fmt);
    }

    xstep = vpc_pipe_get_pixel_step(fmt_info, X);

    return width * bytes / xstep;
}

img_rank_type_e vpc_pipe_get_fmt_rank(const vpc_fmt_info_t *fmt_info)
{
    return fmt_info->rank;
}

down_sample_coeff_t vpc_pipe_get_uvdown_coeff(const vpc_fmt_info_t *fmt_info)
{
    return fmt_info->down_sample_coeff;
}

uint8_t vpc_pipe_get_uvup_en(const vpc_fmt_info_t *fmt_info)
{
    return fmt_info->uvup_en;
}

swap_t vpc_pipe_get_swap_cfg(const vpc_fmt_info_t *fmt_info)
{
    return fmt_info->swap;
}

static void vpc_pipe_init_swap_cfg(vpc_fmt_info_t *fmt_info)
{
    switch (fmt_info->rank) {
        case NV12: SET_SWAP_CFG(1, 0xe1, 0xe1); break;
        case YUYV: SET_SWAP_CFG(1, 0x93, 0x39); break;
        case YVYU: SET_SWAP_CFG(1, 0xb1, 0xb1); break;
        case UYVY: SET_SWAP_CFG(1, 0xc6, 0xc6); break;
        case YUV:  SET_SWAP_CFG(1, 0xc6, 0xc6); break;
        case YVU:  SET_SWAP_CFG(1, 0xc9, 0xd2); break;
        case UVY:  SET_SWAP_CFG(1, 0xe1, 0xe1); break;
        case RGB:  SET_SWAP_CFG(1, 0xc6, 0xc6); break;
        case RGBA: SET_SWAP_CFG(1, 0xc6, 0xc6); break;
        case ARGB: SET_SWAP_CFG(1, 0x1b, 0x1b); break;
        case ABGR: SET_SWAP_CFG(1, 0x39, 0x93); break;
        case NV21: SET_SWAP_CFG(0, 0xe4, 0xe4); break;
        case VYUY: SET_SWAP_CFG(0, 0xe4, 0xe4); break;
        case VUY:  SET_SWAP_CFG(0, 0xe4, 0xe4); break;
        case BGR:  SET_SWAP_CFG(0, 0xe4, 0xe4); break;
        case BGRA: SET_SWAP_CFG(0, 0xe4, 0xe4); break;
        case BGR_PLANAR: SET_SWAP_CFG(0, 0xe4, 0xe4); break;
        case RANK_BUTT:  SET_SWAP_CFG(0, 0xe4, 0xe4); break;
    }
}

void vpc_pipe_init_format_info(vpc_fmt_info_t *fmt_info, vpc_pipe_pic_fmt_t format)
{
    int32_t ret = vpc_pipe_init_yuv_field_format_info(fmt_info, format);
    if (ret == 0) {
        vpc_pipe_init_swap_cfg(fmt_info);
        return;
    }

    ret = vpc_pipe_init_gray_field_format_info(fmt_info, format);
    if (ret == 0) {
        vpc_pipe_init_swap_cfg(fmt_info);
        return;
    }

    ret = vpc_pipe_init_rgb_field_format_info(fmt_info, format);
    if (ret == 0) {
        vpc_pipe_init_swap_cfg(fmt_info);
        return;
    }

    return;
}